package org.xurui.bsj.protocol.command.impl;

import lombok.extern.slf4j.Slf4j;
import org.jetlinks.core.message.CommonDeviceMessage;
import org.jetlinks.core.message.DeviceMessage;
import org.jetlinks.core.message.codec.EncodedMessage;
import org.jetlinks.core.message.codec.FromDeviceMessageContext;
import org.jetlinks.core.message.function.FunctionInvokeMessage;
import org.jetlinks.core.message.function.FunctionInvokeMessageReply;
import org.jetlinks.core.message.function.FunctionParameter;
import org.xurui.bsj.protocol.cache.ConcurrentMapCache;
import org.xurui.bsj.protocol.command.CmdCodec;
import org.xurui.bsj.protocol.enums.CommandEnum;
import org.xurui.bsj.protocol.msg.BsjMessage;
import org.xurui.bsj.protocol.msg.BsjMessageBuilder;
import org.xurui.bsj.protocol.utils.ArrayUtils;
import org.xurui.bsj.protocol.utils.BinaryUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 4.2.7.设置区域报警 （暂不使用）
 */
@Slf4j
public class CmdCodec_SET_REGIONAL_ALARM implements CmdCodec {
    @Override
    public boolean supportsCmd(String cmd) {
        return CommandEnum.SET_REGIONAL_ALARM.name().equals(cmd);
    }

    @Override
    public List<DeviceMessage> parsePayload(BsjMessage payload, FromDeviceMessageContext context) {
        //例子：[35380100360174,898600MFSSYYGXXXXXXP,201805082000001000,SET_REGIONAL_ALARM,2,20180528111820,1,0]
        FunctionInvokeMessageReply report = FunctionInvokeMessageReply.create();
        report.setDeviceId(payload.getHeader().getDeviceNo());
        report.setFunctionId(payload.getHeader().getCmd());
        Object messageIdObj = ConcurrentMapCache.getInstance().getAndRemove(payload.getHeader().getOrderNo());
        String messageId = messageIdObj==null?null:messageIdObj.toString();
        if(messageId==null){
            messageId = payload.getHeader().getOrderNo();
        }
        report.setMessageId(messageId);
        report.setTimestamp(System.currentTimeMillis());
        Map<String, Object> properties = new HashMap<>();
        String tempBody = payload.getTempBody();
        String[] tempBodyArr = tempBody.split("@");
        //properties.put("header", FastBeanCopier.copy(payload.getHeader(), HashMap::new));
        properties.put("header", payload.getHeader().toMap());
        //应答状态(0=设置成功;1=设置异常;)
        properties.put("responseStatus", ArrayUtils.getStrByIndex(tempBodyArr,0));
        report.setOutput(properties);
        return genDeviceMessage(report);
    }

    @Override
    public EncodedMessage encodeMessage(CommonDeviceMessage message,String zzs) {
        //平台下发消息
        //例子：[35380100360174,898600MFSSYYGXXXXXXP,201805082000001000,SET_REGIONAL_ALARM,1,20180528111820,100,1@1@Round*2*(24.513972491956064#117.72402112636269)*(1000)@3@1130-1230+1330-1430+@1+2+3+4+]
        /**
         * 报文体格式： 操作代码
         *            @请求状态
         *            @形状*元素个数*元素值 1*元素值 2*...*元素值 n
         *            @区域编号
         *            @时间段
         *            @周期字段
         * 说明如下:   1.操作代码：1 表示新增区域 2 表示修改区域 3 表示删除区域(报文体仅上传操作代码和区域代码，删除 时报文格式不变，其他参数补 0) 目前新增和修改状态的处理是一样的，都是按照报文更新信息。≥
         *           2.请求状态：1 表示父亲卡 2 表示母亲卡
         *           3.形状*元素个数*元素值 1*元素值 2*...*元素值 n：取 值如Round （ 注 ： 代 表 圆 ） *2* （24.513972491956064#117.72402112636269）（注： 圆心经纬度）*（1000）（注：半径，单位：米） Rectangle(注：代表矩形)*2*（39.123456，136.123456） (注：矩形左上角坐标)*（39.823456，136.823456） （注：矩形右下角坐标） Polygon（注：代表多边形,多边形最多 8 个点）*4* （ 24.513972491956064#117.72402112636269 ） * （ 24.513972491956064#117.724021126362696 ） * （ 24.513972491956064#117.72402112636269 ） * （24.513972491956064#117.72402112636269）
         *           4.区域编号：当前操作区域编号，如 3
         *           5.时间段：当前区域的时间范围，最多设置两个时间 段（开始时间-结束时间+开始时间-结束时间+）， 如：0800-1130+1330-1730+
         *           6.周期：周一至周六用 1-6 表示，周日用 0 表示，以+ 号连接，如 1+2+3+4+表示周一至周四
         */
        if(message instanceof FunctionInvokeMessage) {
            FunctionInvokeMessage m = (FunctionInvokeMessage) message;
            List<FunctionParameter> params = m.getInputs();
            Map<String, Object> paramsMap = params.stream()
                .collect(Collectors.toMap(FunctionParameter::getName, FunctionParameter::getValue));
            String  opCode="";
            if(paramsMap.get("opCode")!=null && !paramsMap.get("opCode").equals("")) {
                opCode=paramsMap.get("opCode").toString();
            }

            String requestStatus="";
            if(paramsMap.get("requestStatus")!=null && !paramsMap.get("requestStatus").equals("")) {
                requestStatus=paramsMap.get("requestStatus").toString();
            }

            String  shapeElement="";
            if(paramsMap.get("shapeElement")!=null && !paramsMap.get("shapeElement").equals("")) {
                shapeElement=paramsMap.get("shapeElement").toString();
            }

            String areaNo="";
            if(paramsMap.get("areaNo")!=null && !paramsMap.get("areaNo").equals("")) {
                areaNo=paramsMap.get("areaNo").toString();
            }

            String  timeQuantum="";
            if(paramsMap.get("timeQuantum")!=null && !paramsMap.get("timeQuantum").equals("")) {
                timeQuantum=paramsMap.get("timeQuantum").toString();
            }

            String cycle="";
            if(paramsMap.get("cycle")!=null && !paramsMap.get("cycle").equals("")) {
                cycle=paramsMap.get("cycle").toString();
            }


            StringBuffer sb = new StringBuffer();
            sb.append(opCode);
            sb.append(BinaryUtils.CMD_AT);
            sb.append(requestStatus);
            sb.append(BinaryUtils.CMD_AT);
            sb.append(shapeElement);
            sb.append(BinaryUtils.CMD_AT);
            sb.append(areaNo);
            sb.append(BinaryUtils.CMD_AT);
            sb.append(timeQuantum);
            sb.append(BinaryUtils.CMD_AT);
            sb.append(cycle);

            return BsjMessageBuilder.create().buildBsjFunctionInvoickMessage(m,sb.toString());
        }else{
            if (log.isDebugEnabled()) {
                log.debug("非FunctionInvokeMessage指令{}消息{}",CommandEnum.SET_REGIONAL_ALARM.name(),message);
            }
            return null;
        }

    }
}
